package com.gopay.cron.service.cloud.impl;

import com.gopay.common.constants.trans.OrderFeePayer;
import com.gopay.common.constants.trans.PayChannel;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.datasource.DBType;
import com.gopay.common.datasource.DbContextHolder;
import com.gopay.common.domain.cloud.CloudFileDownloadInfo;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.user.dao.CloudFileDownloadInfoDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.cron.service.cloud.CloudAccountStatementGenService;
import com.gopay.cron.service.cloud.gen.CloudOrderFileGenHelper;
import com.gopay.cron.web.vo.CloudAccountStatementVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 云账户对账文件生成Service实现类
 * Created by sh.jiao on 2017/2/20.
 */

@Service("cloudAccountStatementGenService")
public class CloudAccountStatementGenServiceImpl implements CloudAccountStatementGenService {

    private static Logger logger = Logger.getLogger(CloudAccountStatementGenServiceImpl.class);

    @Resource(name = "commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;

    @Resource(name = "cloudFileDownloadInfoDAO")
    private CloudFileDownloadInfoDAO cloudFileDownloadInfoDAO;

    @Override
    public boolean genFile(String filePath,String checkDate,String custId, String acctId,String prodCode) {
        CloudOrderFileGenHelper helper = queryOrder(checkDate,custId,acctId);
        StringBuilder genPath = new StringBuilder();
        genPath.append(filePath).append(checkDate).append(File.separator)
                .append(custId).append(File.separator).append(acctId).append(File.separator);
        helper.setFilePath(genPath.toString());
        helper.setProdCode(prodCode);
        helper.setCheckDate(checkDate.replace("-",""));
        try {
            helper.genFile();
        } catch (Exception e) {
            logger.error("生成文件出错",e);
            return false;
        }
        return true;
    }

    @Override
    public void cleanYesterdayFileDownloadNum(Set<String> custIds) {
        if(custIds != null && !custIds.isEmpty()) {
            String hql = "FROM CloudFileDownloadInfo c WHERE c.custId IN (:custIds)";
            Map<String, Object> param = new HashMap<>();
            param.put("custIds",new ArrayList<String>(custIds));
            List<CloudFileDownloadInfo> list = cloudFileDownloadInfoDAO.findByHql(hql,param);
            if(list != null && !list.isEmpty()) {
                for(CloudFileDownloadInfo info : list) {
                    info.setDayDownloadNum(0);
                    cloudFileDownloadInfoDAO.update(info);
                }
            }
        }
    }


    private CloudOrderFileGenHelper queryOrder(String checkDate,String custId,String acctId) {
        DbContextHolder.setDbType(DBType.DS_ONLY_READ.value);
        String beginTime = checkDate + " 00:00:00";
        String endTime = checkDate + " 23:59:59";
        List<Object[]> list = commonQueryDAO.findBySql(buildQuerySql(custId,acctId,beginTime,endTime));
        return buildResult(list,custId,acctId);
    }

    private CloudOrderFileGenHelper buildResult(List<Object[]> list,String custId,String acctId) {

        CloudOrderFileGenHelper helper = new CloudOrderFileGenHelper();
        if(list != null) {
            for(int i = 0;i<list.size();i++) {
                Object[] obj = list.get(i);
                CloudAccountStatementVO vo = new CloudAccountStatementVO();
                vo.setGopayOrderId((String) obj[0]);
                vo.setMerOrderId((String) obj[1]);
                vo.setGopayIntTxnCd(translateGopayIntTxnCd((String) obj[3]));
                vo.setReqTime(DateUtils.format((Date) obj[4],"yyyy-MM-dd HH:mm:ss"));
                vo.setTranFinishTime(DateUtils.format((Date) obj[5],"yyyy-MM-dd"));
                if(obj[6] != null && !"".equals(obj[6])) {
                    vo.setMerTxnAmt(((BigDecimal) obj[6]).setScale(2).toString());
                } else {
                    vo.setMerTxnAmt(new BigDecimal(0).setScale(2).toString());
                }
                vo.setOrderFeePayer((String) obj[8]);
                vo.setGopayAcct(acctId);
                if (IntTxnCd._00100.value.equals(obj[3])) {
                    //手续费
                    if (OrderFeePayer.PAY_PAYER.value.equals(vo.getOrderFeePayer())) {
                        vo.setOrderFeeAmt(new BigDecimal(0).setScale(2).toString());
                    } else if(obj[9] != null  && !"".equals(obj[9])) {
                        vo.setOrderFeeAmt(((BigDecimal) obj[9])
                                .setScale(2, RoundingMode.HALF_UP).toString());
                    } else {
                        vo.setOrderFeeAmt(new BigDecimal(0).setScale(2).toString());
                    }
                    //佣金
                    if("06".equals(obj[12]) && (obj[0] != null && !"".equals(obj[0]))) { //云账户交易
                        List<Object[]> receipts = commonQueryDAO.findBySql(buildMerCommAmtQuerySql((obj[0]).toString()));
                        if(receipts != null && !receipts.isEmpty()) {
                            Object[] receipt = receipts.get(0);
                            vo.setMerCommAmt(((BigDecimal)receipt[1])
                                    .setScale(2 ,RoundingMode.HALF_UP).toString());
                        }
                    } else {
                        vo.setMerCommAmt(new BigDecimal(0).setScale(2).toString());
                    }

                    //入账金额(交易金额 + 佣金 - 手续费)
                    vo.setRealAmt(new BigDecimal(vo.getMerTxnAmt())
                            .add(new BigDecimal(vo.getMerCommAmt()))
                            .subtract(new BigDecimal(vo.getOrderFeeAmt()))
                            .setScale(2, RoundingMode.HALF_UP).toString());
                    vo.setPayChannel(PayChannel.translate((String) obj[7]));

                    helper.addRecvFileLine(vo);

                } else if (IntTxnCd._01200.value.equals(obj[3])) {
                    DbContextHolder.setDbType(DBType.DS_ONLY_READ.value);
                    List<Object[]> refunds = commonQueryDAO.findBySql(buildRefundQuerySql(vo.getGopayOrderId()));
                    if (refunds != null && !refunds.isEmpty()) {
                        Object[] refund = refunds.get(0);
                        vo.setOrigMerOrderId((String) refund[1]);
                        vo.setOrigMerTxnAmt(((BigDecimal)refund[2])
                                .setScale(2, RoundingMode.HALF_UP).toString());
                        //已退还手续费(需根据原订单的手续费承担方来判断)
                        if (OrderFeePayer.PAY_PAYER.value.equals(refund[4])) {
                            vo.setRefundFeeAmt(new BigDecimal(0).setScale(2).toString());
                        } else if(refund[0] != null && !"".equals(refund[0])) {
                            vo.setRefundFeeAmt(((BigDecimal)refund[0])
                                    .setScale(2, RoundingMode.HALF_UP).toString());
                        } else {
                            vo.setRefundFeeAmt(new BigDecimal(0).setScale(2).toString());
                        }
                        vo.setPayChannel(PayChannel.translate((String) refund[3]));

                        //退款手续费
                        if(OrderFeePayer.PAY_PAYER.value.equals(vo.getOrderFeePayer())
                                && (obj[9] != null && !"".equals(obj[9]))) {
                            vo.setOrderFeeAmt(((BigDecimal) obj[9])
                                    .setScale(2, RoundingMode.HALF_UP).toString());
                        } else {
                            vo.setOrderFeeAmt(new BigDecimal(0).setScale(2).toString());
                        }
                        //出账金额
                        vo.setRealAmt(new BigDecimal(vo.getMerTxnAmt())
                                .subtract(new BigDecimal(vo.getRefundFeeAmt()))
                                .add(new BigDecimal(vo.getOrderFeeAmt()))
                                .setScale(2, RoundingMode.HALF_UP).toString());
                    }

                    helper.addRefundFileLine(vo);
                } else if (IntTxnCd._01812.value.equals(obj[3])) {
                    vo.setRecvAcctId((String) obj[2]);
                    if (OrderFeePayer.REC_PAYER.value.equals(vo.getOrderFeePayer())) {
                        vo.setOrderFeeAmt(new BigDecimal(0).setScale(2).toString());
                    } else if(obj[9] != null  && !"".equals(obj[9])) {
                        vo.setOrderFeeAmt(((BigDecimal)obj[9])
                                .setScale(2, RoundingMode.HALF_UP).toString());
                    } else {
                        vo.setOrderFeeAmt(new BigDecimal(0).setScale(2).toString());
                    }
                    List<Object[]> rels = commonQueryDAO.findBySql(buildCloudAcctRelQuerySql(custId, acctId, vo.getRecvAcctId()));
                    if (rels != null && !rels.isEmpty()) {
                        Object[] rel = rels.get(0);
                        //将收款方账户号变更为协议号
                        vo.setRecvAcctId((String) rel[0]);
                    }

                    helper.addTransferFileLine(vo);
                } else if (IntTxnCd._00700.value.equals(obj[3])) {
                    //手续费
                    if(OrderFeePayer.PAY_PAYER.value.equals(vo.getOrderFeePayer())
                            && (obj[9] != null && !"".equals(obj[9]))) {
                        vo.setOrderFeeAmt(((BigDecimal) obj[9])
                                .setScale(2, RoundingMode.HALF_UP).toString());
                    } else {
                        vo.setOrderFeeAmt(new BigDecimal(0).setScale(2).toString());
                    }
                    if("06".equals(obj[12]) && (obj[11] != null && !"".equals(obj[11]))) { //云账户交易
                        List<Object[]> rels = commonQueryDAO.findBySql(buildAgreeIdQuerySql((obj[11]).toString()));
                        if (rels != null && !rels.isEmpty()) {
                            Object[] rel = rels.get(0);
                            //将收款方账户号变更为协议号
                            vo.setRecvAcctId((String) rel[0]);
                        }
                    } else {
                        vo.setRecvAcctId("");
                    }
                    helper.addPayFileLine(vo);
                }
            }

        }
        return helper;
    }

    private String buildMerCommAmtQuerySql(String gopayOrderId) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT t.gopay_order_id,t.mer_tiliu_amt ");
        sql.append("  FROM CPS_GEN_RECEIPT_ORDER t ");
        sql.append(" WHERE t.gopay_order_id = '").append(gopayOrderId).append("'");
        return sql.toString();
    }

    private String buildAgreeIdQuerySql(String transDtlSq) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT t.IN_ACCT, t.trans_dtl_sq  ");
        sql.append("  FROM pg_gen_order_trans_dtl t   ");
        sql.append(" WHERE t.trans_dtl_sq = '").append(transDtlSq).append("'");
        return sql.toString();
    }

    private String buildQuerySql(String custId, String acctId, String beginTime, String endTime) {
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT c.gopay_order_id,                   ");     // 0
        sql.append("        c.mer_order_id,                     ");     // 1
        sql.append("        c.main_recv_acct,                   ");     // 2
        sql.append("        c.gopay_int_txn_cd,                 ");     // 3
        sql.append("        c.mer_txn_tm,                       ");     // 4
        sql.append("        t.tran_time,                        ");     // 5
        sql.append("        c.mer_txn_amt,                      ");     // 6
        sql.append("        c.pay_channel,                      ");     // 7
        sql.append("        c.order_fee_payer,                  ");     // 8
        sql.append("        c.order_real_fee_amt,               ");     // 9
        sql.append("        c.MER_COMM_AMT,                     ");     // 10
        sql.append("        c.TRANS_DTL_SQ,                     ");     // 11
        sql.append("        c.GATEWAY_SOURCE                    ");     // 12
        sql.append(" FROM cps_gen_main_order c       ");
        sql.append(" RIGHT JOIN (SELECT a.gopay_order_id, max(a.tran_time) tran_time    ");
        sql.append("   FROM acps_acct_trans_dtl a     ");
        sql.append("           WHERE a.acct_id = '").append(acctId).append("'");
        sql.append("             and a.cust_id = '").append(custId).append("'");
        sql.append("             and a.tran_time >=     ");
        sql.append("                 to_timestamp('").append(beginTime).append("','yyyy-MM-dd HH24:MI:ss')    ");
        sql.append("             and a.tran_time <=     ");
        sql.append("                 to_timestamp('").append(endTime).append("','yyyy-MM-dd HH24:MI:ss') ");
        sql.append("             group by a.gopay_order_id) t ");
        sql.append(" ON c.gopay_order_id = t.gopay_order_id     ");
        sql.append(" WHERE c.gopay_int_txn_cd in ('00100','01200','01812','00700') ");
        //logger.info("query order sql:["+sql.toString()+"]");
        return sql.toString();
    }

    private String buildRefundQuerySql(String gopayOrderId) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT a.refund_fee_amt,");         // 0
        sql.append("       oc.mer_order_id,");          // 1
        sql.append("       oc.mer_txn_amt,");           // 2
        sql.append("       oc.pay_channel, ");          // 3
        sql.append("       oc.order_fee_payer ");       // 4
        sql.append("  FROM cps_gen_main_order c ");
        sql.append("  left join CPS_GEN_ASSIST_ORDER a ");
        sql.append("  ON c.gopay_order_id = a.gopay_order_id ");
        sql.append("  left join cps_gen_main_order oc ");
        sql.append("  ON c.relevance_gopay_order_id = oc.gopay_order_id ");
        sql.append(" WHERE c.gopay_order_id = '").append(gopayOrderId).append("'");

        //logger.info("query refund order sql:["+sql.toString()+"]");
        return sql.toString();
    }

    private String buildCloudAcctRelQuerySql(String partnerCustId,String partnerAcctId,String acctId) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT t.agree_id,t.acct_id ");
        sql.append("  FROM cloud_cust_acct_rel t ");
        sql.append(" WHERE t.partner_cust_id = '").append(partnerCustId).append("'");
        sql.append("   AND t.partner_acct_id = '").append(partnerAcctId).append("'");
        sql.append("   AND t.acct_id = '").append(acctId).append("'");
        //logger.info("query cloudCustAcctRel sql:["+sql.toString()+"]");
        return sql.toString();
    }

    private String translateGopayIntTxnCd(String gopayIntTxnCd) {
        String result = "";
        if(gopayIntTxnCd != null) {
            switch (gopayIntTxnCd) {
            case "00100" :
                result = "网关支付";
                break;
            case "01200" :
                result = "收款退款";
                break;
            case "01812" :
                result = "云账户转账";
                break;
            case "00700" :
                result = "付款到银行";
                break;
            }
        }
        return result;
    }

}
